package com.raven.play.datalink.evaluate;

import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * 自定义类加载器
 * 保证janino执行时, 只能访问工程中的类以及指定目录下的类
 */
@Slf4j
public class RestrictedClassLoader extends URLClassLoader {

    public RestrictedClassLoader(URL[] urls) {
        super(urls);
    }

    public RestrictedClassLoader(String path) {
        super(getJarURLs(path));
    }

    @SneakyThrows
    private static URL[] getJarURLs(String directoryPath) {
        List<URL> urls = new ArrayList<>();
        File libDir = new File(Objects.requireNonNull(RestrictedClassLoader.class.getClassLoader().getResource(directoryPath)).toURI());
        File[] jars = libDir.listFiles((dir, name) -> name.endsWith(".jar"));

        if (jars != null) {
            for (File jar : jars) {
                urls.add(jar.toURI().toURL());
            }
        }
        return urls.toArray(new URL[0]);
    }

    @Deprecated
    private static URL[] getJarURLs2(String directoryPath) {
        List<URL> urls = new ArrayList<>();
        try {
            Files.walk(Paths.get(directoryPath))
                    .filter(Files::isRegularFile)
                    .filter(path -> path.toString().endsWith(".jar"))
                    .forEach(path -> {
                        try {
                            urls.add(path.toUri().toURL());
                        } catch (IOException e) {
                            throw new RuntimeException("Error loading JAR: " + path, e);
                        }
                    });
        } catch (IOException e) {
            log.error(e.getMessage(), e);
            throw new RuntimeException(e);
        }
        return urls.toArray(new URL[0]);
    }

}
